package token

import (
	"fmt"
	"gitee.com/chejiangyi/bsfgo/core/base2"
	"github.com/golang-jwt/jwt/v5"
	"time"
)

// CustomClaims 自定义JWT声明
type jwtToken struct {
	UserID string         `json:"userid"`
	Attrs  map[string]any `json:"attrs"`
	jwt.RegisteredClaims
}

type Token struct {
	UserID string
	Attrs  map[string]any
}

type JWTTokenStrategy struct {
}

// GenerateJWT 生成JWT Token
func (*JWTTokenStrategy) ToToken(token Token) string {
	claims := jwtToken{
		UserID: token.UserID,
		Attrs:  token.Attrs,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(base2.BsfConfigInstance.GetTokenTTLSeconds()) * time.Second)),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			Issuer:    "bsfGo",
		},
	}
	t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	if tokenStr, err := t.SignedString([]byte(base2.BsfConfigInstance.GetTokenSecretKey())); err == nil {
		return tokenStr
	} else {
		panic(base2.NewBsfError(fmt.Sprintf("签名失败:%v", token.UserID)))
	}
}

// ValidateJWT 验证JWT Token
func (*JWTTokenStrategy) ValidateJWT(tokenString string) *Token {
	var token jwtToken
	t, err := jwt.ParseWithClaims(tokenString, &token, func(token *jwt.Token) (interface{}, error) {
		// 验证签名方法
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			panic(base2.NewBsfError(fmt.Sprintf("签名验证失败: %v", token.Header["alg"])))
		}
		return []byte(base2.BsfConfigInstance.GetTokenSecretKey()), nil
	})
	if err != nil {
		panic(base2.NewBsfError(fmt.Sprintf("token验证失败: %v", tokenString)))
	}
	if claims, ok := t.Claims.(*jwtToken); ok && t.Valid {
		return &Token{UserID: claims.UserID, Attrs: claims.Attrs}
	}
	panic(base2.NewBsfError(fmt.Sprintf("token验证无效: %v", tokenString)))
}
